<?php
/**
 * @name Loader
 *
 * LICENSE
 *
 * This source file is subject to the BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://framework.phpxe.com/license/
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to Chaodong.Sheng <scd113@gmail.com> so we can send you a copy immediately.
 *
 * @category   Scd of Scd Framework
 * @package    Scd
 * @copyright  Copyright (c) 2007 PHPXe Web Studio <http://www.phpxe.com>
 * @license    http://framework.phpxe.com/license/
 * @version    $Id: Scd.php Wed Sep 19 23:46:03 CST 2007 Davy $
 */
 
include_once("Scd/Exception.php");

/**
 * 简写的 DIRECTORY_SEPARATOR
 */
define('DS', DIRECTORY_SEPARATOR);
define('APPNAME', 'SCD');
define('VERSION', '1.0');

/**
 * 定义 Scd PHP 文件所在位置，以及初始的 CLASS_PATH
 */
define('Scd_DIR', dirname(__FILE__));
$GLOBALS[G_Scd_VAR]['CLASS_PATH'] = array(dirname(Scd_DIR));
ini_set('include_path', ini_get('include_path') . PATH_SEPARATOR . $GLOBALS[G_Scd_VAR]['CLASS_PATH'][0]);

class Scd
{
	/**
	 * @param string The name of the property
	 * @param mixed The value of the property to set
	 */
	function set( $property, $value=null ) {
		$this->$property = $value;
	}

	/**
	 * @param string The name of the property
	 * @param mixed  The default value
	 * @return mixed The value of the property
	 */
	function get($property, $default=null)
	{
		if(isset($this->$property)) {
			return $this->$property;
		}
		return $default;
	}
	
	/**
	 * 载入指定类的定义文件
	 *
	 * 用法：
	 * <code>
	 * loadClass('Scd_Helper_Pager');
	 * $pager =& new Scd_Helper_Pager(...);
	 * </code>
	 *
	 * @param string $filename
	 *
	 * @return boolean
	 */
	function loadClass( $class )
	{
		/*if (class_exists($class)) {
			return new Scd_Exception('<u>Can`t find Class:<b>'.$class.'</b></u>');
		}*/

		$parts = explode( '.', $class );
		$parts = array_map(ucfirst, $parts);
		$class = implode( '_', $parts);
		$path = implode( DS, $parts);
		// autodiscover the path from the class name
		//$path = str_replace('.', DIRECTORY_SEPARATOR, $class);
		if ($dirs === null && $path != $class) {
			// use the autodiscovered path
			$dirs = dirname($path);
			$file = basename($path) . '.php';
		} else {
			$file = $class . '.php';
		}

		//引入文件
		Scd::loadFile($file, $dirs, true);

		if (!class_exists($class)) {
			return new Scd_Exception("File \"$file\" was loaded "
			. "but class \"".str_replace( '.', '_', $class)."\" was not found within.");
		}
	}

	/**
	 * loadFile
	 *
	 * @param string $filename
	 * @param string|null $dirs
	 * @param boolean $once
	 * @return include
	 */
	function loadFile($filename, $dirs=null, $once=true)
	{
		// security check
		if (preg_match('/[^a-z0-9\-_.]/i', $filename)) {
			return new Scd_Exception('Security check: Illegal character in filename');
		}
		/**
         * Determine if the file is readable, either within just the include_path
         * or within the $dirs search list.
         */
		$filespec = $filename;
		if ($dirs === null) {
			$found = Scd::isReadable($filespec);
		} else {
			foreach ((array)$dirs as $dir) {
				$filespec = rtrim($dir, '\\/') . DIRECTORY_SEPARATOR . $filename;
				$found = Scd::isReadable($filespec);
				if ($found) {
					break;
				}
			}
		}

		/**
         * Throw an exception if the file could not be located
         */
		if (!$found) {
			return new Scd_Exception("File \"$filespec\" was not found.");
		}

		/**
         * Attempt to include() the file.
         *
         * include() is not prefixed with the @ operator because if
         * the file is loaded and contains a parse error, execution
         * will halt silently and this is difficult to debug.
         *
         * Always set display_errors = Off on production servers!
         */
		//        echo $filespec;exit;s
		if ($once) {
			return include_once $filespec;
		} else {
			return include $filespec ;
		}
	}

	function isReadable($filename)
	{
		if (is_readable($filename)) {
			return true;
		}

		$path = get_include_path();
		$dirs = explode(PATH_SEPARATOR, $path);

		foreach ($dirs as $dir) {
			// No need to check against current dir -- already checked
			if ('.' == $dir) {
				continue;
			}

			if (is_readable($dir . DIRECTORY_SEPARATOR . $filename)) {
				return true;
			}
		}

		return false;
	}
	
	function & factory($class, $options)
	{
		Scd::loadClass( $class );
		$parts = explode( '.', $class );
		$parts = array_map(ucfirst, $parts);
		$class = implode( '_', $parts);
		$obj = new $class( $options );
		return $obj;
	}
	
	function toString()
	{
		echo get_class($this);
	}
}
?>